﻿/**
 * ImgLoader Class
 *
 * @author Carl Ogren
 * @version 0.2
 * @revision 4
 * 
 * This class loads an image from a server and displays it.
 * It can toggle to fullscreen by clicking on the image.
 * The image can be displayed with an offset in normal display, fullscreen display, both or none.
 * A progress bar can be displayed and positioned to show the image loading progress,
 * of course the progress bar component has to be included into the library for this to work.
 * An example of usage:

// import packages
import rasdev.utils.ImgLoader;

// store stage handle
var swfStage:Stage = this.stage;

// Retrieve flashvar parameters
var imgURL:String = loaderInfo.parameters.path;

// Create image loader
var imgLoader:ImgLoader = new ImgLoader({
	// These parameters are necessary
	url: imgURL,
	swfStage: swfStage,
	
	// These parameters are optional
	offset: 10,
	offsetBehaviour: "fullscreen",
	showPb: true,
	pbAlign: "center",
	align: "top left",
	fsAlign: "center",
	linkFullScreen: true,
	fit2Stage: true,
	loadOnCreate: true,
	loadErrorText: "Oups... Could not load image"
});

 *
 */

package rasdev.utils {
	
	// import flash display components
	import flash.display.MovieClip;
	import flash.display.Stage;
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.StageDisplayState;
	import flash.display.StageScaleMode;
	import flash.display.StageAlign;
	
	// import flash ui components
	import flash.ui.Mouse;
	import flash.ui.MouseCursor;
	
	// import flash text components
	import flash.text.TextField;
	
	// import flash net components
	import flash.net.URLRequest;
	
	// import flash events
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.ProgressEvent;
	import flash.events.IOErrorEvent;
	import flash.events.FullScreenEvent;
	
	// import fl controls
	import fl.controls.ProgressBar;
	
	
	
	
	
	public class ImgLoader {
		
		var url:String;	// Image url
		
		private var ctnr:MovieClip;	// Container movie clip
		private var swfStage:Stage;	// Stage handle
		
		private var bmp:Bitmap;		// Loaded image
		private var bmpWidth:int;	// Initial image width
		private var bmpHeight:int;	// Initial image height
		
		private var pb:ProgressBar;		// Progressbar control handle
		
		public var showPb:Boolean			= true;	// Show loading progress bar
		public var pbAlign:String			= "center" // Position of the progress bar if shown
		public var linkFullScreen:Boolean	= true;	// Allow toggle to fullscreen mode by clicking on the image
		public var fit2Stage:Boolean		= true;	// Resize image according to the stage size
		public var loadOnCreate:Boolean		= true;	// Loads the image from the constructor
		public var align:String				= "top left"	// Alignment of the image in normal display
		public var fsAlign:String			= "center"		// Alignment of the image in fullscreen display
		public var offset:int				= 0;	// Image position offset
		public var offsetBehaviour:String	= "always";
		public var loadErrorText:String		= "Could not load image...";	// Loading error message
		
		
		
		// ImgLoader constructor
		public function ImgLoader(param) {
			// Create movie clip and add to stage if not exists
			if (typeof param.container == "undefined") {
				param.container = new MovieClip();
				param.swfStage.addChild(param.container);
			}
			
			// Store parameters
			url = param.url;
			ctnr = param.container;
			swfStage = param.swfStage;
			
			offset			= typeof param.offset == "undefined" ? offset : param.offset;
			offsetBehaviour	= typeof param.offsetBehaviour == "undefined" ? offsetBehaviour : param.offsetBehaviour;
			align			= typeof param.align == "undefined" ? align : param.align;
			fsAlign			= typeof param.fsAlign == "undefined" ? fsAlign : param.fsAligng;
			showPb			= typeof param.showPb == "undefined" ? showPb : param.showPb;
			pbAlign			= typeof param.pbAlign == "undefined" ? pbAlign : param.pbAlign;
			linkFullScreen	= typeof param.linkFullScreen == "undefined" ? linkFullScreen : param.linkFullScreen;
			fit2Stage		= typeof param.fit2Stage == "undefined" ? fit2Stage : param.fit2Stage;
			loadErrorText	= typeof param.errorMessage == "undefined" ? loadErrorText : param.errorMessage;
			loadOnCreate	= typeof param.loadOnCreate == "undefined" ? loadOnCreate : param.loadOnCreate;
			
			// Prevent scene from scalling and align it in the top left corner of the stage
			swfStage.scaleMode	= StageScaleMode.NO_SCALE;
			swfStage.align		= StageAlign.TOP_LEFT;
			
			// Bind resize events
			if (fit2Stage && fit2Stage != "once") {
				swfStage.addEventListener(Event.RESIZE, function(e:Event) {
					resizeCtnr(e);
				});
			}
			
			// Bind fullscreen events
			if (linkFullScreen) {
				ctnr.addEventListener(MouseEvent.MOUSE_OVER, function(e:MouseEvent) {
					flash.ui.Mouse.cursor = flash.ui.MouseCursor.BUTTON;
				});
				ctnr.addEventListener(MouseEvent.MOUSE_OUT, function(e:MouseEvent) {
					flash.ui.Mouse.cursor = flash.ui.MouseCursor.ARROW;
				});
				ctnr.addEventListener(MouseEvent.CLICK, toggleFullScreen);
				ctnr.addEventListener(FullScreenEvent.FULL_SCREEN, resizeCtnr);
			}
			
			// Load image
			if (loadOnCreate) {
				if (!loadImg()) {
					loadError();
				}
			}
		}
		
		
		// Load image into container
		public function loadImg():Boolean {
			// Create Loader
			var reqLoader:Loader = new Loader();
			
			// Create progressbar
			if (showPb) {
				pb = new ProgressBar();
				pb.source = reqLoader.contentLoaderInfo;
				
				setPbPosition();
				
				ctnr.addChild(pb);
			}
			
			if (url == "" || url == null) {
				return false;
			}
			
			// Create url request
			var reqURL:URLRequest = new URLRequest(url);
			
			// Bind loading events
			reqLoader.contentLoaderInfo.addEventListener(Event.INIT, loadInit);
			reqLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
			reqLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
			reqLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadError);
			
			// load image
			reqLoader.load(reqURL);
			
			return true;
		}
		
		
		// Image has been downloaded and is being initialized
		private function loadInit(e:Event) {
			
		}
		
		
		// Image is ready to be drawn on screen
		private function loadComplete(e:Event) {
			// Store image data
			bmp = e.target.loader.content as Bitmap;
			// Enable smoothing filter (without this the quality of the image when resized is really poor)
			bmp.smoothing = true;
			
			// Image initial width and height
			bmpWidth = bmp.width;
			bmpHeight = bmp.height;
			
			if (showPb) { ctnr.removeChild(pb); }
			ctnr.addChild(bmp);
			
			// Resize container to image size then resize container to stage size
			if (fit2Stage || fit2Stage == "once") {
				ctnr.width = bmpWidth;
				ctnr.height = bmpHeight;
				
				resizeCtnr();
			}
		}
		
		
		// Image loading progress
		private function loadProgress(e:ProgressEvent) {
			
		}
		
		
		// Image loading error
		private function loadError(e:IOErrorEvent = null) {
			var errorText:TextField = new TextField();
			errorText.text = loadErrorText;
			
			errorText.width = swfStage.stageWidth;
			
			if (showPb) { ctnr.removeChild(pb); }
			ctnr.addChild(errorText);
		}
		
		// Retrieve container maximum size according to offset and fullscreen state
		private function getMaxSize():Object {
			var maxWidth:int;
			var maxHeight:int;
			
			// Determine maxWidth and maxHeight of the container according to offset and fullscreen state
			if (swfStage.displayState != StageDisplayState.FULL_SCREEN) {
				if (/always|normal/.test(offsetBehaviour)) {
					maxWidth = swfStage.stageWidth - (offset * 2);
					maxHeight = swfStage.stageHeight - (offset * 2);
				}
				else {
					maxWidth = swfStage.stageWidth;
					maxHeight = swfStage.stageHeight;
				}
			}
			else {
				if (/always|fullscreen/.test(offsetBehaviour)) {
					maxWidth = swfStage.stageWidth - (offset * 2);
					maxHeight = swfStage.stageHeight - (offset * 2);
				}
				else {
					maxWidth = swfStage.stageWidth;
					maxHeight = swfStage.stageHeight;
				}
			}
			
			return {maxWidth: maxWidth, maxHeight: maxHeight};
		}
		
		
		// resize container to stage size
		public function resizeCtnr(e:Event = null):void {
			var maxSize:Object = getMaxSize();
			
			var maxWidth:int = maxSize.maxWidth;
			var maxHeight:int = maxSize.maxHeight;
			
			// Limit the size of the container to the original size of the image
			// to avoid resizing the image to a larger size than its actual resolution
			if (maxWidth > bmpWidth) { maxWidth = bmpWidth; }
			if (maxHeight > bmpHeight) { maxHeight = bmpHeight; }
			
			// Resize container according to maxWidth
			ctnr.width = maxWidth;
			ctnr.scaleY = ctnr.scaleX;
			
			// If container height exceeds maxHeight, resize container according to maxHeight
			if (ctnr.height > maxHeight) {
				ctnr.height = maxHeight;
				ctnr.scaleX = ctnr.scaleY;
			}
			
			maxSize = getMaxSize();
			
			maxWidth = maxSize.maxWidth;
			maxHeight = maxSize.maxHeight;
			
			// Determine container x and y positions according to offset, fullscreen state and alignment
			if (swfStage.displayState != StageDisplayState.FULL_SCREEN) {
				if (/left/i.test(align)) { ctnr.x = 0; }
				else if (/center|centerX/i.test(align)) { ctnr.x = (maxWidth - ctnr.width) / 2;	}
				else if (/right/i.test(align)) { ctnr.x = maxWidth - ctnr.width; }
				
				if (/top/i.test(align)) { ctnr.y = 0; }
				else if (/center|centerY/i.test(align)) { ctnr.y = (maxHeight - ctnr.height) / 2; }
				else if (/bottom/i.test(align)) { ctnr.y = maxHeight - ctnr.height; }
				
				if (/always|normal/.test(offsetBehaviour) && offset != 0) {
					ctnr.x += offset;
					ctnr.y += offset;
				}
			}
			else {
				if (/left/i.test(fsAlign)) { ctnr.x = 0; }
				else if (/center|centerX/i.test(fsAlign)) { ctnr.x = (maxWidth - ctnr.width) / 2; }
				else if (/right/i.test(fsAlign)) { ctnr.x = maxWidth - ctnr.width; }
				
				if (/top/i.test(fsAlign)) { ctnr.y = 0; }
				else if (/center|centerY/i.test(fsAlign)) { ctnr.y = (maxHeight - ctnr.height) / 2; }
				else if (/bottom/i.test(fsAlign)) { ctnr.y = maxHeight - ctnr.height; }
				
				if (/always|fullscreen/.test(offsetBehaviour) && offset != 0) {
					ctnr.x += offset;
					ctnr.y += offset;
				}
			}
			
			setPbPosition();
		}
		
		// Determine the progress bar x and y positions
		private function setPbPosition():void {
			var maxSize:Object = getMaxSize();
			
			var maxWidth:int = maxSize.maxWidth;
			var maxHeight:int = maxSize.maxHeight;
			
			// Progress bar position
			if (/left/i.test(pbAlign)) { pb.x = 0; }
			else if (/center|centerX/i.test(pbAlign)) { pb.x = (maxWidth - pb.width) / 2; }
			else if (/right/i.test(pbAlign)) { pb.x = maxWidth - pb.width; }
			
			if (/top/i.test(pbAlign)) { pb.y = 0; }
			else if (/center|centerY/i.test(pbAlign)) { pb.y = (maxHeight - pb.height) / 2; }
			else if (/bottom/i.test(pbAlign)) { pb.y = maxHeight - pb.height; }
		}
		
		
		// toggle fullscreen mode
		public function toggleFullScreen(event:Event):void {
			if (swfStage.displayState != StageDisplayState.FULL_SCREEN) {
				swfStage.displayState = StageDisplayState.FULL_SCREEN;
			}
			else {
				swfStage.displayState = StageDisplayState.NORMAL;
			}
		}
		
	}
	
}
